feat(projects): add agent and CLI project-home support - #6590
feat(projects): add agent and CLI project-home support#6590thomaspblock wants to merge 16 commits into
Conversation
Give agents bounded project-home context and project-aware CLI operations while keeping channel matching client-filtered through the existing relay query surface. Signed-off-by: Thomas Petersen <thomasp@squareup.com>
thomaspblock
left a comment
There was a problem hiding this comment.
Cassandra adversarial/security review — needs work
The red Unit Tests job is not caused by this diff: it fails linking untouched buzz-voice with could not find native static library 'sherpa-onnx-c-api'. That check should be retried rather than patched in this projects PR.
I found two source-level blockers independently while tracing the new project-home resolution.
P1 — Any relay writer can hijack a channel's agent project context and redirect channel-scoped issues (confidence 100)
Evidence
crates/buzz-acp/src/prompt_project.rs:23-25:!event_is_unlisted(event) && event_has_tag_value(event, "buzz-channel", channel_id)crates/buzz-acp/src/prompt_project.rs:27-33: the matching events are ordered only bycreated_at, then the first parseable event wins.crates/buzz-cli/src/commands/project_channel.rs:27-31:let project = pick_oldest_listed(&projects);followed byif let Some(member) = first_member_repo(event) { return Ok(member); }docs/nips/NIP-MP.md:139:`buzz-channel` on a project is **metadata only**.docs/nips/NIP-MP.md:188:The relay MUST NOT check whether the signer owns, maintains, or has any relationship to a member repository.
Trigger scenario
- An attacker who knows a project channel UUID publishes a listed
kind:30621carrying thatbuzz-channeland anatag for the attacker's repository. This is protocol-valid and requires no authority over the channel. - The attacker gives it an earlier accepted timestamp than the legitimate project (or simply publishes before project creation).
- ACP selects that event as the channel's project home and promotes its name/owner/repository into generated
[Context]instructions. buzz issues create --channel <victim-channel>independently makes the same oldest-event choice and returns the attacker's first member coordinate without checking that the project signer controls the channel or that the member repo is actually bound to it.- A normal “create a task in this project” request is therefore signed against an unrelated attacker-chosen repository.
This crosses an integrity boundary: unauthenticated project metadata is being treated as authoritative routing configuration. Resolve the project from an authenticated channel-owned binding/type, or require a verifiable relationship between the selected project signer and channel authority. At minimum, channel-scoped repo resolution must verify the selected 30617 is bound to the requested channel and reject ambiguous projects rather than choosing oldest.
P1 — Global slug squatting lets any signer block another user's project creation (confidence 100)
Evidence
crates/buzz-cli/src/commands/projects.rs:373-379:other_listed_project(&fetch_projects_by_dtag(client, slug).await?, &caller_pubkey)causes a conflict when any other pubkey has the slug.docs/nips/NIP-MP.md:134:Only the signer can replace their (pubkey, 30621, d) coordinate.docs/nips/NIP-MP.md:194:newest created_at wins per (pubkey, 30621, d), and one pubkey can never overwrite another's coordinate.
Trigger scenario
An attacker publishes listed projects for common slugs (app, website, a known upcoming product name). Every later buzz projects create <slug> by every other identity is rejected locally, even though the protocol intentionally namespaces projects by signer. The suggested error action (“Add a repository to that project instead”) cannot work because editing is signer-only. Do not impose relay-wide uniqueness on an owner-namespaced coordinate; duplicate-card prevention needs an authority-scoped rule.
Additional adversarial risk retained in this PR comment
crates/buzz-cli/src/commands/project_channel.rs:178-185 adds the selected foreign project owner as a maintainers tag on an implicitly created caller-owned repository. Under docs/nips/NIP-MP.md:215-217, that tag is sufficient claim authority for the foreign signer. I did not live-test Desktop's resulting fold, but this should be removed or explicitly justified before merge; untrusted project metadata must not grant provenance/claim authority over a newly created repo.
Coverage: full 12-file diff read; traced ACP project lookup → generated context, CLI channel lookup → issue creation, implicit repo creation, project collision checks, NIP-MP authority and claim semantics. I did not mutate the branch or run a live hostile relay reproduction.
Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
thomaspblock
left a comment
There was a problem hiding this comment.
Cassandra re-review of 7a9af2ac — one routing blocker remains
The original two P1 findings are fixed in the authoritative-selection path: foreign channel/project claims no longer route ACP or CLI, ambiguity fails closed, cross-signer slug/channel squatting is removed, and implicit repo creation no longer grants foreign maintainers authority.
P1 — Existing same-id repository bypasses the new channel-binding check (confidence 100)
Evidence
crates/buzz-cli/src/commands/project_channel.rs:181-188:if let Some(existing) = crate::commands::repos::fetch_own_repo_announcement(client, &repo_id).await? { let _ = try_add_own_repo_to_channel_project(client, channel, &repo_id).await; return Ok(ChannelProjectRepo { repo_owner: existing.pubkey.to_hex(), repo_id, }); }
- The new binding check exists in
repo_from_announcementat lines 94-104, but this fallback does not call it.
Trigger scenario
- The caller already owns repo
30617:<caller>:app, bound to channel A (or unbound). - They own a repository-empty project home with slug
appin channel B. buzz issues create --channel Bfinds no authoritative project/member and no caller-owned repo bound to B, then reachesensure_default_repo.fetch_own_repo_announcement("app")returns the channel-A repository. The code attaches it to the channel-B project and returns it without checking or rebinding itsbuzz-channel.- The issue is silently created against channel A's unrelated repository. Subsequent calls repeat the same misrouting, while ACP correctly refuses to recognize that member as authoritative for B.
The fallback must apply the same first-buzz-channel equality invariant before returning. If an existing same-id repo is bound elsewhere, fail with an actionable conflict or choose a non-colliding id; do not attach or route to it.
Advisory — maintainer authorization reads only the first value (confidence 75)
Evidence
crates/buzz-cli/src/commands/project_channel.rs:88-91:|| repo.tags.iter().any(|tag| { matches!(tag.as_slice(), [name, value, ..] if name == "maintainers" && value.eq_ignore_ascii_case(&signer)) })
crates/buzz-acp/src/prompt_project.rs:93-101likewise returns onlytag.get(1)for eachmaintainerstag.VISION_PROJECTS.md:27and NIP-34 modelmaintainersas a multi-value tag; Desktop deliberately reads all values (desktop/src/features/projects/projectModels.ts:283-285).
A valid ['maintainers', first, project_signer] repository authorizes the signer in Desktop but is rejected by both new routing implementations. Iterate all values after the tag name so ACP, CLI, and Desktop share one authority rule.
Re-review coverage: exact fix diff a6c5f1db..7a9af2ac; traced authoritative selection, ambiguity, project creation collisions, implicit repo fallback, and maintainer parsing. Report-only; no branch mutation.
Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
thomaspblock
left a comment
There was a problem hiding this comment.
Cassandra final security/authority re-review — findings cleared at 7bbed3f1
No remaining security or adversarial findings in the incremental fix.
Verified:
crates/buzz-cli/src/commands/project_channel.rs:197-205now callsrequire_repo_channel_bindingbefore reusing or attaching a same-slug existing repository, so a repository bound to channel A cannot route a channel-B issue.require_repo_channel_bindinguses the firstbuzz-channelvalue, matching the relay's fail-closed binding semantics, and rejects both mismatched and absent bindings.- ACP's
multi_tag_valuesand CLI'stag.as_slice()[1..]now inspect every pubkey value in everymaintainerstag, matching NIP-34/Desktop semantics. - Regressions cover the mismatched existing binding and authorization by a later maintainer value.
- The prior fixes remain intact: project-home selection requires a channel-bound live member repository plus signer authority; ambiguity fails closed; cross-signer slug/channel squatting is absent; implicit creation does not grant foreign maintainer authority.
Verdict for my security/authority lane: merge-ready at exact head 7bbed3f127f25559fc301044842ee6582b2fdc9a. CI and independent correctness review are outside this verdict and were still in progress when checked.
## Summary - create explicit NIP-MP projects with a home channel and default repository - preserve standalone repository folding, project deletion, and deterministic repository selection - restore Template, Team, visibility, and agent settings in the project creation flow This is Part 2 of the channel-first Projects stack, following #6590. It is independently based on `main`; Part 3 adds the project-home channel surface. ## Testing - focused project collection, creation, channel, and model tests: 38/38 passed - Desktop unit suite: 5,415/5,415 passed - TypeScript, Biome, and differential file-size checks passed - full pre-push gate passed ## Post-Deploy Monitoring & Validation - create listed and unlisted projects with and without templates in the first staging Desktop session - healthy signals: one home channel, one default repository, stable project coordinates, and no duplicate legacy card - failure signals: partial project creation, duplicate projects, missing default repository, or stale sidebar entries; mitigate by reverting this PR --------- Signed-off-by: Thomas Petersen <thomasp@squareup.com>
## Summary - classify and render project-home channels through the shared channel glyph and lifecycle helpers - let the normal channel pane host a project idle auxiliary surface and focus drawer - align channel management, headers, member bars, and empty-channel actions with project channel semantics This is Part 3 of the channel-first Projects stack, based on #6591. Part 4 adds the project-home navigation and context experience. ## Testing - focused channel lifecycle, pane helper, and project-home channel tests: 7/7 passed - Desktop unit suite: 5,422/5,422 passed - E2E-mode Desktop build passed - TypeScript, Biome, and differential file-size checks passed - full pre-push gate passed ## Post-Deploy Monitoring & Validation - open normal, temporary, private, and project-home channels in the first staging Desktop session - healthy signals: normal channels retain their existing composer/thread behavior and project homes use the project glyph and auxiliary slot - failure signals: missing composer, incorrect channel kind, stuck focus drawer, or project chrome on a normal channel; mitigate by reverting this PR --------- Signed-off-by: Thomas Petersen <thomasp@squareup.com> Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
## Summary - render an explicit project's home channel through the normal channel timeline and composer - add a resizable project context rail with codebase, channel, people, and workspace navigation - keep project agent conversations bounded to the project home and preserve repository/detail routes This is Part 4 of the channel-first Projects stack, based on #6594. The final part contains overview and workspace completion polish. ## Testing - focused project conversation, route, summary, workspace-sheet, and related-channel tests: 39/39 passed - Desktop unit suite: 5,439/5,439 passed - E2E-mode Desktop build passed - TypeScript, Biome, and differential file-size checks passed - full pre-push gate passed ## Post-Deploy Monitoring & Validation - open project homes from project and channel entry points in the first staging Desktop session - healthy signals: one channel timeline/composer, stable repository context, bounded project agent history, and reversible workspace sheets - failure signals: duplicate channel surfaces, stale repository selection, unrelated DM history, or sheets replacing the channel route; mitigate by reverting this PR Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
| fn truncate_repo_name(name: &str) -> String { | ||
| if name.len() <= 128 { | ||
| return name.to_string(); | ||
| } | ||
| name.chars().take(128).collect() | ||
| } |
There was a problem hiding this comment.
The guard measures bytes but the truncation takes chars, while build_repo_announcement rejects names over 128 bytes. A multibyte project name over 128 bytes still exceeds the byte limit after chars().take(128), so default-repo creation errors instead of truncating (e.g. a 100-CJK-character name). Same pattern in projects.rs ensure_default_create_repo, which has no byte check at all — truncate on a byte budget at a char boundary, as the prompt-side truncation does.
🤖
There was a problem hiding this comment.
Fixed in 2e0fe69: both default-repository paths now share UTF-8-safe truncation on a 128-byte budget, with a CJK regression test.
| const workspaceSheet = | ||
| workspaceSheetOpen && workspaceSheetTab && workspaceRepository ? ( | ||
| <ProjectHomeWorkspaceSheet | ||
| key={`${workspaceSheetTab}:${workspaceRepository.id}`} | ||
| identityPubkey={identityQuery.data?.pubkey} | ||
| onOpenCommit={handleOpenCommit} | ||
| onRepositoryAdded={handleFilesAdded} | ||
| onSelectRepository={setWorkspaceRepositoryId} | ||
| project={project} | ||
| projects={projects} | ||
| repository={workspaceRepository} | ||
| tab={workspaceSheetTab} | ||
| /> | ||
| ) : null; |
There was a problem hiding this comment.
workspaceSheet is a fresh JSX element every render and flows into the memoized ChannelPane as idleAuxiliaryPanel, so while the sheet is open any parent render (query cache updates, local state) defeats React.memo(ChannelPane) and re-renders the whole message timeline behind the drawer — the exact unstable-prop gotcha the repo docs call out. Its inputs are all stable callbacks/ids, so wrapping the construction in React.useMemo restores the memo boundary.
🤖
There was a problem hiding this comment.
Fixed in 2e0fe69: the conditional workspace sheet element is memoized with its complete dependency set, preserving the downstream ChannelPane memo boundary.
| if (homeChannel) { | ||
| const alreadyMember = homeChannel.memberPubkeys.some( | ||
| (pubkey) => | ||
| normalizePubkey(pubkey) === normalizePubkey(selectedAgent.pubkey), | ||
| ); | ||
| if (!alreadyMember) { | ||
| await addChannelMembers({ | ||
| channelId: homeChannel.id, | ||
| pubkeys: [selectedAgent.pubkey], | ||
| role: "bot", | ||
| }); | ||
| } | ||
| } |
There was a problem hiding this comment.
The bot member-add is gated on homeChannel being set, not on the message actually targeting it. restoreProjectsAgentConversation can restore a 1:1 DM while homeChannelId is set, and submitProjectAgentMessage then sends to the DM — in that case this block silently adds the agent as a bot member of the project home channel as a side effect of a DM follow-up. Guard on the resolved target, e.g. only add when !conversation || conversation.channel.id === homeChannel.id.
🤖
There was a problem hiding this comment.
Fixed in 2e0fe69: bot membership is now added only when the resolved existing conversation is the project home channel (or no conversation exists yet).
Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
thomaspblock
left a comment
There was a problem hiding this comment.
Cassandra security re-review of 2e0fe6999 — one tenant-scope blocker remains
Matt's three reported defects are correctly fixed: UTF-8 names now truncate to a 128-byte prefix at a character boundary in both callers, the CJK regression passes, the workspace-sheet element has a complete useMemo dependency set, and an existing DM no longer triggers project-home membership.
P1 — Project-home membership is not bound to the captured relay/signer scope (confidence 75)
Evidence
desktop/src/features/projects/ui/ProjectAgentChatPanel.tsx:167-171:await addChannelMembers({ channelId: homeChannel.id, pubkeys: [selectedAgent.pubkey], role: "bot", });
- The immediately following agent start/open/send path passes the captured
relayScopeand signer atProjectAgentChatPanel.tsx:183-201, but this membership mutation passes neither. desktop/src/shared/api/types.ts:88-92exposes no expected relay/signer fields onAddChannelMembersInput.desktop/src-tauri/src/commands/channels.rs:533-559accepts only channel/pubkeys/role and calls unscopedsubmit_event(builder, &state).desktop/src-tauri/src/relay/submit.rs:71-77resolves the currently active relay and signing keys when called.
Trigger scenario
- The panel captures project home channel A, relay A, and signer A.
- The user submits while a community or identity switch races the Tauri membership command (or the switch occurs after this unscoped await starts).
add_channel_membersresolves the then-active workspace and signs/publishes the captured channel UUID there; if that UUID exists in relay B, the bot membership is mutated in the wrong tenant. Even without a collision, the wrong-relay failure occurs outside the later fail-closed path.submitProjectAgentMessagethen checksexpectedRelayUrl/expectedSignerPubkeyand fails closed, leaving membership as a partial side effect even though no project message was sent.
This contradicts the nearby invariant that “every relay side effect” is scope-bound. Extend the membership command/API with expected relay and signer parameters and perform the same assert/captured-target submission used by the message path, or move the membership operation into a scoped orchestration boundary. The channel-target guard fixes Matt's DM case but not this tenant race.
Verification: reviewed exact incremental diff 7d6c4abce..2e0fe6999; git diff --check passed; independently ran the new CJK test at exact head (1 passed). Report-only; no branch mutation.
Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
Cassandra security/adversarial re-review —
|
jedwards27
left a comment
There was a problem hiding this comment.
:bot: Jude’s code review agent — request changes
Reviewed base e23632941331502c0330e51d407e667bea26ef57 through exact head adff0acff7f5fbe61795aad6e3a5670e1300b45d against VISION.md, VISION_PROJECTS.md, TESTING.md, NIP-MP authority semantics, the ACP resolver/cache, CLI project/repository routing, relay query execution, and the changed Desktop project journeys.
P1 — reject a same-slug repository bound outside the new project home
crates/buzz-cli/src/commands/projects.rs:372-380 adds the coordinate returned by ensure_default_create_repo to the project and publishes it. But ensure_default_create_repo at projects.rs:665-670 returns any caller-owned same-ID repository without checking its buzz-channel. This omits the binding invariant already enforced for issue-time reuse at crates/buzz-cli/src/commands/project_channel.rs:171-182,197-205.
If the caller already owns repo app bound to channel A (or with no binding), buzz projects create app --channel B reports success and publishes a channel-B project containing the channel-A repo. ACP correctly refuses to treat that member as authoritative for B, and later channel-scoped issue routing conflicts rather than targeting the advertised project. Apply the same binding check before reuse (or fail before project publication), with a regression for mismatched and absent bindings.
P1 — do not permanently cache project absence or mutable project metadata
crates/buzz-acp/src/pool.rs:598-611 caches Option<PromptProjectInfo> indefinitely, including None; fetch_project_home_for_channel explicitly treats empty as final at pool.rs:2986-2989. There is no TTL, relevant-event invalidation, or session-boundary refresh.
If ACP resolves channel C before its project/repository publication completes, it caches None. Creating the project later cannot add the Project block to any later turn/session in that process until restart. Positive entries likewise retain obsolete project names/default repositories. Use bounded freshness or invalidate on relevant project/repository events, and regress None → project resolution without restarting ACP.
P1 — do not treat a truncated global query page as authoritative absence
The project-home paths issue one-shot 1,000-row queries: ACP at crates/buzz-acp/src/pool.rs:2993-3003, CLI projects at crates/buzz-cli/src/commands/projects.rs:74-86, and CLI repositories at crates/buzz-cli/src/commands/project_channel.rs:160-168. The relay clamps the SQL query to 1,000 at crates/buzz-relay/src/handlers/req.rs:957-960, while non-single-letter custom-tag matching occurs only after that limited read at crates/buzz-relay/src/api/bridge.rs:1308-1315; the SQL tag pushdown at req.rs:1001-1044 covers #p/#d, not #buzz-channel.
Once more than 1,000 newer visible heads exist, an older authoritative project or repository can be excluded by unrelated global rows. ACP then resolves (and permanently caches) no project; CLI channel routing can say the channel is not a project home or take fallback behavior. BuzzClient already exposes composite-cursor pagination at crates/buzz-cli/src/client.rs:683-729. Page to a defined exhaustive/bounded result with explicit truncation failure, or add indexed relay-side support; a full page cannot prove absence. Add coverage that places the authoritative head beyond page one.
Validation and residual risk
- Clean exact-head
cargo test -p buzz-cli -p buzz-acppassed (809 + 9 + 374 tests; one doc test ignored); clippy for both packages passed with-D warnings. - Desktop unit suite passed 5,451/5,451; Desktop check/typecheck passed; five targeted create/open/retry/lost-ack/sidebar project journeys passed.
- Keyboard Enter/Space and
aria-pressedbehavior, a 900×720 viewport at 24px root text, control visibility, and horizontal overflow were probed successfully in the browser artifact. No additional source-level product/accessibility blocker was found. - All applicable exact-head GitHub checks are green. Those checks do not exercise the three failure shapes above.
- Residual product risk: no exact-head native Tauri/WebView journey or native receipt was available for the materially changed navigation/layout, so native focus, OS input, and shell resizing remain unproven.
- The 1,001-head starvation case was established from the client/relay control flow, not reproduced against a seeded live relay.
Gauge correctness/testing verification of Jude's three P1s — all confirmed at exact head
|
Cassandra security/adversarial response to Jude's review — exact head
|
Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
Cassandra security/adversarial re-review — exact head
|
jedwards27
left a comment
There was a problem hiding this comment.
:bot: Jude’s code review agent — REQUEST CHANGES at exact head e1b1f1b8f7a20cda01a6c4116cd6a22dce79f440 (base db5617dd1541aeab7bacaf039b6ca98f856776d0).
The same-slug binding guard and 30-second ACP cache expiry fix the original permanent-staleness paths, and pagination removes the old 1,000-row cutoff. Two author-actionable correctness defects remain:
P1 — ACP turns bounded-discovery failure into authoritative non-project context
fetch_project_home_for_channel still globally enumerates kind 30621 projects without #buzz-channel (crates/buzz-acp/src/pool.rs:3000-3007) even though this head adds relay SQL pushdown for that tag. query_raw_all errors after 10,000 events (crates/buzz-acp/src/relay.rs:443-459), and the whole enumeration must also complete inside one three-second timeout (pool.rs:3016-3034). Either failure is retried and then collapsed through Option to None; lookup_project caches that absence for 30 seconds (pool.rs:604-624). The resulting agent session is indistinguishable from a legitimate ordinary channel even though ACP could not prove project absence. This moves the starvation wall rather than removing it.
Required fix: query projects by #buzz-channel, preserve lookup failure as an error/retry state instead of cacheable absence, and add causal regressions for an authoritative project beyond page one plus bound/timeout failure that cannot become ordinary-channel context.
P1 — project creation can publish after losing the default-repository write
ensure_default_create_repo preflights once, submits the repository announcement, discards the relay write response, and returns the coordinate (crates/buzz-cli/src/commands/projects.rs:669-694). cmd_create then publishes the project with that coordinate (projects.rs:383-405). In a concurrent same-identity create, another event can win the (owner, 30617, slug) replaceable head with a different or absent home binding; this invocation's write may be duplicate/dominated, but the ignored response still allows the project publication to report success. ACP then rejects the advertised repository as authoritative for that home.
Required fix: require an accepted/non-dominated repository write, re-read and verify the winning head is bound to the requested home before project publication, make retry/partial-publication recovery idempotent and truthful, and add a deterministic lost-write race regression.
Re-review evidence
- Source contract reviewed against
VISION.md,VISION_PROJECTS.md, andTESTING.md. - Clean exact-head
cargo test -p buzz-cli -p buzz-acp: 810 + 9 + 374 passed; one CLI doc test ignored. - Clean exact-head
just desktop-test: 5,451/5,451 passed. - Same-slug mismatched/unbound repository reuse is now rejected; permanent positive/negative ACP caching is replaced with a shared 30-second TTL. Cache mutation coverage remains weaker than the contract, but those former permanent-staleness defects are cleared subject to the failure-collapse issue above.
- No new actionable React/UI/accessibility defect was found in this head's Rust/relay correction delta. Native focus/resize behavior was not re-observed; Desktop smoke/integration checks are green, so that is reviewer-tooling residual risk rather than author action.
- GitHub
Unit Testsis red because untouchedbuzz-voicecannot linksherpa-onnx-c-api. The PR does not touchbuzz-voice,Cargo.lock, CI workflows, orjustfile; this is a CI/tooling-owned required-gate failure, not a request to change project-home code. It still needs a green terminal gate before merge.
Verification ownership: author supplies the two causal regressions and fixes; I will re-review the resulting exact head. CI/tooling owners restore or retry the unrelated required Unit Tests gate.
jedwards27
left a comment
There was a problem hiding this comment.
:bot: Jude’s code review agent
Verdict: REQUEST CHANGES
Reviewed: db5617dd1541aeab7bacaf039b6ca98f856776d0..e1b1f1b8f7a20cda01a6c4116cd6a22dce79f440 (exact head e1b1f1b8f7a20cda01a6c4116cd6a22dce79f440)
Risk: high — project-home authority, repository/channel binding, relay discovery, ACP prompt context, and multi-event CLI publication.
Behavior/contracts traced: project creation and default-repository publication, winning-head authority, ACP project-context lookup/cache lifecycle, composite relay pagination and custom-tag SQL filtering, issue/project routing, and failure/partial-write behavior. The previous same-slug binding defect is fixed (crates/buzz-cli/src/commands/projects.rs:677-679); permanent ACP caching is replaced by a 30-second TTL (crates/buzz-acp/src/pool.rs:604-623); CLI/ACP now paginate rather than treating one 1,000-row page as exhaustive. Two author-actionable failures remain.
P1 — ACP turns failed bounded discovery into authoritative “not a project” context
fetch_project_home_for_channel returns only Option<PromptProjectInfo> (crates/buzz-acp/src/pool.rs:3000-3043). It still queries the global kind-30621 project set without #buzz-channel (:3004-3007), although singleton #buzz-channel SQL pushdown now exists. query_raw_all rejects more than 10,000 events (crates/buzz-acp/src/relay.rs:443-459), and each whole paginated lookup is wrapped by one three-second timeout (pool.rs:3016-3034). Bound, timeout, and query failures are retried and then collapsed to None; lookup_project caches that value for 30 seconds (pool.rs:604-623). The agent therefore receives ordinary non-project context when discovery explicitly could not establish absence. This moves the old starvation wall rather than fixing the session-boundary truthfulness contract.
Author action: query project heads by #buzz-channel now that relay-side pushdown exists, and preserve lookup failure/indeterminate state rather than converting it to cacheable absence. Add causal regressions with the authoritative project beyond page one and with bound/timeout failure, proving neither yields normal-channel context.
Verification owner: author for code/tests; reviewer for mutation and exact-head integration rerun.
P1 — project creation can publish a project after losing the default-repository write
ensure_default_create_repo preflights once, signs and submits the repository, but discards the relay response and immediately returns the coordinate (crates/buzz-cli/src/commands/projects.rs:669-694). cmd_create then publishes the project containing it (:390-405). Unlike project submission (:251-260), the repository step neither calls parse_write_response nor re-reads the winning repository head/binding. Two clients can both observe no repository; a conflicting repository head can win while this write is duplicate/dominated, yet this invocation still reports a successfully created project whose advertised default repository is not authoritative for the home.
Author action: require an accepted/non-dominated repository write, then re-read and verify the winning head is bound to the requested home before publishing the project. Make retry/recovery idempotent and partial state explicit. Add a deterministic concurrent/dominated-write regression that fails if the repository response is ignored.
Verification owner: author for code and race regression; reviewer for exact-head rerun.
Validation: clean exact-head cargo test -p buzz-cli -p buzz-acp passed (810 + 9 + 374 tests; one doc test ignored); git diff --check passed. Exact-head Rust/desktop/build/E2E/security checks were observed green except required Unit Tests, which failed while linking untouched buzz-voice because sherpa-onnx-c-api was unavailable. That gate is CI/tooling-owned and is not additional author work for this PR.
Manual/native evidence: no exact-head native Tauri/WebView project-home journey or seeded >page-one relay reproduction was run. The blocks above follow from deterministic control flow and missing write-response authority checks.
Residual risk: native focus/input/resize behavior and a live high-cardinality relay remain reviewer/tooling confidence gaps. The 30-second cache intentionally permits bounded metadata staleness after a successful lookup.
Gauge re-review — correctness/testing/reliability (exact head
|
Cassandra adversarial re-review of
|
Gauge correctness/testing verification of Jude's round-3 review — exact head
|
Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> # Conflicts: # desktop/src/features/channels/ui/ChannelPane.tsx # desktop/src/features/channels/ui/FocusThreadDrawer.tsx
Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
Cassandra security/adversarial re-review — exact head
|
Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
Cassandra final security/adversarial re-review — exact head
|
jedwards27
left a comment
There was a problem hiding this comment.
:bot: Jude’s code review agent
One P1 remains: an expired cached project absence can still turn a failed refresh into authoritative ordinary-channel context.
ChannelInfoResolver::lookup_project now correctly propagates failure when no cache entry exists. But after an entry expires, the refresh-error branch returns any stale value as Ok(stale.value) (crates/buzz-acp/src/pool.rs:635-646). When the stale value is None, resolve() accepts it as proven project absence (pool.rs:604-617). A legitimate initial miss, 30-second expiry, subsequent project publication, and relay timeout therefore causes the managed agent to receive ordinary-channel context precisely when project authority is indeterminate.
Both review lanes independently established this path. A causal mutation of the new regression preseeded expired CachedProjectInfo { value: None }; failed_project_lookup_through_resolve_cannot_become_ordinary_context then failed at the ordinary-context assertion. The checked-in test covers only an empty cache, so it misses this branch.
Author action: after refresh failure, never return stale None as authoritative absence. Propagate ProjectLookupError so resolve() suppresses ordinary-channel context. Retaining stale positive metadata may be reasonable if intentional, but distinguish it explicitly. Add an initial miss → expiry → failed refresh regression through resolve(), and mutation-prove removing the stale-negative guard fails it.
The other prior P1 is fixed: default-repository creation now parses the relay write result, re-reads the winning replaceable head, verifies its home binding, and only then publishes the project; exact-head causal tests cover a foreign-home winner and matching-home idempotence.
Exact-head evidence at 7c630f5a9aca8eca7d851c35e9a8056e7b921ec9: cargo test -p buzz-cli -p buzz-acp passes 812 + 9 + 376 tests (one doc test ignored); cargo fmt --all -- --check and delta git diff --check pass; causal mutations for no-cache lookup failure and dominated repository-write verification fail at their intended assertions. Current Rust CI reds were not attributed without completed logs; affected local suites are green. Live high-cardinality/timeout relay observation remains a confidence gap, not another author defect.
jedwards27
left a comment
There was a problem hiding this comment.
Verdict: REQUEST CHANGES
Reviewed: f6e6617a9dcc2308d5039f8afaab974b49fb9577..7c630f5a9aca8eca7d851c35e9a8056e7b921ec9 (exact head 7c630f5a9aca8eca7d851c35e9a8056e7b921ec9)
Risk: high — project discovery controls whether managed agents receive project authority/context; an indeterminate relay result must not be collapsed into ordinary-channel context.
Blocking finding
P1 — an expired cached absence converts refresh failure into authoritative non-project context.
ChannelInfoResolver::lookup_project returns any stale cache entry after a failed refresh (crates/buzz-acp/src/pool.rs:635-646). When that stale entry is None, resolve() accepts it as authoritative absence (pool.rs:604-617) and returns ordinary stream metadata.
Concrete sequence:
- A lookup legitimately caches
None. - The 30-second cache TTL expires.
- The channel becomes a project home (or the prior miss was incomplete).
- Refresh times out/errors.
lookup_projectreturnsOk(None), so the prompt proceeds as an ordinary channel despite project authority being indeterminate.
The checked-in regression at pool.rs:8566-8614 covers only the empty-cache failure path. An exact-head mutation that preseeded an expired CachedProjectInfo { value: None } made failed_project_lookup_through_resolve_cannot_become_ordinary_context fail at its ordinary-context assertion (rc=101), confirming the uncovered branch.
Author action: never return stale negative cache as proven absence after refresh failure. Propagate ProjectLookupError for stale None so resolve() suppresses ordinary-channel context. Add a causal regression for initial miss → cache expiry → failed refresh → indeterminate result. Retaining stale positive project metadata may remain if that degraded mode is intentional and tested; mutation-delete the negative-cache guard and require the regression to fail.
Verification owner: author for fix/regression; :bot: Jude’s code review agent for exact-head mutation and affected package rerun.
Resolved prior findings
- The no-cache lookup failure now remains indeterminate through the real
resolve()boundary; its mutation control failed as intended. - The default-repository dominated-write path now re-reads and verifies the winning
(owner, 30617, d)head before publishing kind 30621 (crates/buzz-cli/src/commands/projects.rs:669-716). Exact-head causal tests cover foreign-home rejection and matching-home idempotence; bypassing winner verification made the rejection test fail as intended.
Validation
At clean exact head 7c630f5a9aca8eca7d851c35e9a8056e7b921ec9:
cargo test -p buzz-cli -p buzz-acp— PASS: 812 + 9 + 376 tests; one CLI doc test ignored.cargo fmt --all -- --check— PASS.git diff --check 86bf4946..7c630f5a— PASS.- Two causal mutation controls for the resolved paths — failed at intended assertions; source restored and tree clean.
- Stale-negative-cache mutation reproduction — FAIL (
rc=101) at the intended ordinary-context assertion, establishing the blocker.
GitHub Rust Lint, Unit Tests, and Windows Rust were red at review time; local affected suites and formatting passed, and those CI failures are not attributed to this PR here without completed log classification.
Manual/native evidence: none at this head. The latest delta contains Rust test changes only; inherited Desktop evidence is supporting evidence, not exact-head native proof.
Residual risk: no live-relay timeout-after-cached-miss reproduction; deterministic resolver mutation establishes the control flow. CI failure classification remains tooling-owned and does not replace the author-actionable defect above.
Gauge correctness/testing re-review — exact head
|
| Mutation (reintroduce the bug) | Test | Result |
|---|---|---|
resolve() degrades Err to ok().flatten() (old F4 behavior) |
failed_project_lookup_through_resolve_cannot_become_ordinary_context |
FAILED (killed) |
Drop #buzz-channel from the project filter (global scan) |
resolve_finds_authoritative_project_beyond_first_bridge_page |
FAILED (killed) |
Revert to client.submit_event(event).await?; Ok(repo_id) (discard response, no re-read) |
create_does_not_publish_project_after_default_repo_loses_to_foreign_home |
FAILED (killed) |
Unmutated full run at the exact head: cargo test -p buzz-acp -p buzz-cli → exit 0, buzz-acp lib 812 passed / 0 failed, no failures in any target. The CLI race regression also asserts the strongest possible postcondition — posted kinds are exactly [30617] on Conflict and [30617, 30621] on idempotent success.
Conflict resolutions verified
FocusThreadDrawer.tsx: main's fix(messages): route edits to the owning composer #6575hasActiveEditprop retained (now optional with default, still wired:ChannelPane.tsx:513hasActiveEdit={threadEditTarget !== null}), PR'slabelprop added.ChannelPane.tsx: main's edit-routing logic moved wholesale intouseRoutedMessageEdit.ts(semantics preserved line-for-line, including the context-invalidation ref dance and"Finish or cancel your edit first."toast thatmessaging.spec.ts:3118/3337/3533/3589assert on); PR's idle-auxiliary-panel behavior retained.
F1 (P2, confidence 100) — Rust Lint and Windows Rust CI failures at this head are real and author-owned
clippy::useless_vec in the new pagination test:
- Source:
crates/buzz-acp/src/pool.rs:8637—let responses = vec![ - CI: Rust Lint job 97592908638 —
error: could not compile `buzz-acp` (lib test) due to 1 previous error/note: `-D clippy::useless-vec` implied by `-D warnings`; Windows Rust job 97592909049 fails on the same lint (error: useless use of 'vec!').
One-line fix (array literal instead of vec![], as clippy suggests). This means the head needs one more push regardless, and the CI gate must be re-run fresh at the fixed head.
Note: just check / push hooks passing locally while clippy fails in CI means the local hook set does not run just clippy with -D warnings — worth knowing, not author work here beyond the fix.
Unit Tests CI failure — infra, not author work (confidence 100)
Job 97592908646: could not find native static library `sherpa-onnx-c-api` while building untouched buzz-voice. Same tooling failure Jude already classified as CI-owned at the previous head; unchanged by this PR.
F2 (P2, confidence 75) — same unverified-write pattern in the sibling channel-project path
crates/buzz-cli/src/commands/project_channel.rs:226 — client.submit_event(event).await?; in ensure_default_repo discards the write response and does no winning-head re-read before returning ChannelProjectRepo { repo_owner: caller, .. }. This is the exact defect class P1-2 fixed in projects.rs, in PR-introduced code (this file does not exist on main). A dominated write here leaves the channel-project flow claiming caller-owned repo authority it may not have. Either fix in this PR with the same submit→parse→re-read→bind pattern, or file as a durable residual — flagging for the author/Jude to scope.
Residual (confidence 50) — stale-retention path has no direct unit test
The Err-with-prior-cache branch (pool.rs:638-644, return Ok(stale.value)) is implemented but no test in pool.rs's test module exercises refresh-failure-with-cached-value (searched the test mod for retain/stale; the two new tests cover Err-without-cache and pagination). If this branch regressed to returning Err or dropping the cache, no test would fail. Small gap; follow-up material, not a blocker.
Verified clean at this head (scoped)
- No production-code changes in
7c630f5a9itself (test-only:pool.rstest mod +projects.rstest mod — verified via diff). is_dm_channelcorrectly switched toresolve_channel_metadataso the author-gate DM check no longer depends on project lookup success (lib.rs:294).- Desktop suite at the merge lineage: 5,486 tests claimed by Wrench; Desktop Core/E2E checks were green at
86bf4946band are in progress at7c630f5a9— the clippy push will re-run them anyway.
Verdict: fixes and regressions are correct and causally tested; NOT merge-ready at this exact head. The useless_vec clippy failure requires one more push, and F2 needs an explicit scope decision. I'll re-verify the incremental diff and the full check-runs sweep at the next pushed head.
Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
Cassandra security/adversarial re-review — exact head
|
jedwards27
left a comment
There was a problem hiding this comment.
:bot: Jude’s code review agent — REQUEST CHANGES
Reviewed: f6e6617a9dcc2308d5039f8afaab974b49fb9577..73d4e2aaafa16156a40b986256038779277cb360 (exact head 73d4e2aaafa16156a40b986256038779277cb360)
Risk: high — this changes project authority discovery, ACP prompt context, relay query scope, and multi-event CLI routing/publication. Two author-actionable defects remain.
P1 — expired cached absence still becomes authoritative ordinary-channel context after refresh failure
ChannelInfoResolver::resolve treats Ok(None) as proven non-project context (crates/buzz-acp/src/pool.rs:604-617). After the 30-second TTL expires, lookup_project returns every stale cache value when refresh fails (pool.rs:620-646). If the stale value is None, a legitimate earlier miss followed by project creation and a relay timeout/error therefore emits ordinary-channel context precisely when project authority is indeterminate.
The checked-in tests cover no-cache failure (pool.rs:8566-8614) and expired-negative successful refresh (pool.rs:8501-8563), but not expired-negative refresh failure. A review-only causal regression seeded expired CachedProjectInfo { value: None }, served malformed responses for both attempts, and required resolve(id).await.is_none(); it failed at the intended assertion (exit 101). The incremental 7c630f5a..73d4e2aa delta does not change this branch.
Author action: on refresh failure, never return stale None as proven absence. Propagate ProjectLookupError so resolve() fails closed. If retaining stale Some(project) is the intended availability policy, test it separately. Add initial miss → TTL expiry → failed refresh coverage through resolve(), and mutation-prove removal of the stale-negative guard fails.
Verification owner: author for fix/regression; :bot: Jude’s code review agent for exact-new-head mutation and full buzz-acp package rerun.
P1 — channel-aware CLI discovery applies its 10,000-event bound before channel scoping
fetch_projects_for_channel queries every kind-30621 project community-wide, calls query_all_bounded(..., 10_000), and only then filters buzz-channel client-side (crates/buzz-cli/src/commands/projects.rs:70-97). Once a community has more than 10,000 project heads, every caller of this helper can hard-fail even when the requested channel has one unambiguous project (projects.rs:182,368; project_channel.rs:30).
The relay pushdown introduced in this stack already supports the narrow query, and ACP already uses "#buzz-channel": [channel] for both project and repository discovery (crates/buzz-acp/src/pool.rs:3039-3047). The CLI omitted that scope.
Author action: add "#buzz-channel": [channel] to the CLI project filter; retain client-side matching as defense in depth. Add a causal regression proving more than 10,000 unrelated projects cannot prevent target-channel resolution, and mutation-prove removing the pushed-down tag filter fails it.
Verification owner: author for fix/regression; :bot: Jude’s code review agent for exact-new-head mutation and full buzz-cli package rerun.
Resolved in this head
The sibling issue-time default-repository race now parses the write result, re-reads the winning replaceable head, verifies its home binding, and only then mutates the project (crates/buzz-cli/src/commands/project_channel.rs:217-234). Its deterministic foreign-winner regression passed at the exact head.
Validation and confidence gaps
- Remote PR head, local
HEAD, and reviewed head all matched73d4e2aaafa16156a40b986256038779277cb360; checkout was clean. Authenticated reviewerjedwards27differs from authorthomaspblock. cargo fmt --all -- --checkandgit diff --check f6e6617a..HEADpassed.- Focused checked-in ACP cache tests and the new CLI foreign-winner regression passed. One reviewer’s full
cargo test -p buzz-acp -p buzz-clirun passed (812 ACP + 9 lifecycle + 377 CLI); my independent full run hit two pre-existing ACP timing-test failures (idle_resets_on_stdout_activity,keepalive_resets_idle_past_deadline) while all 810 other ACP tests passed. This is a confidence/gate issue, not a third author defect. - Exact-head CI completed red.
Unit Testsfailed before tests becausesherpa-onnx-syscould not findsherpa-onnx-c-api; no PR-source causality was established. Desktop Smoke E2E shard 3 had two persistent failures and one flaky failure, including the PR-relevant project conversation retry journey timing out while waiting for the Channels tab. Other Desktop core, integration, relay, Rust lint, Windows, security, macOS build, and release-candidate checks passed. Author action: none for these unclassified gate failures. Verification owner: CI/Desktop gate owners must rerun/classify and obtain required green terminal checks; route author action only if a PR-caused failure is established. - No exact-head native Tauri/WebView project-home journey or live >10,000-project relay reproduction was run. The two blockers are established by deterministic control flow plus the cache mutation; native/live observation remains reviewer/tooling residual risk.
Gauge round-5 review — head
|
Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
Cassandra re-review —
|
jedwards27
left a comment
There was a problem hiding this comment.
:bot: Jude’s code review agent — REQUEST CHANGES
Reviewed: f6e6617a9dcc2308d5039f8afaab974b49fb9577..b4e1d8c13c795dc799f6d8dfaee1be7fb532114b (exact head b4e1d8c13c795dc799f6d8dfaee1be7fb532114b)
Risk: high — project discovery decides ACP authority/context and CLI routing under community-wide relay cardinality. The new-head delta repairs one Desktop E2E navigation step but leaves both prior production defects unchanged.
P1 — expired cached absence becomes ordinary-channel context after refresh failure
ChannelInfoResolver::resolve treats Ok(None) as proven non-project context (crates/buzz-acp/src/pool.rs:604-617). After the 30-second TTL expires, lookup_project returns every stale cache value when refresh fails (pool.rs:624-644). If the stale value is None, an earlier legitimate miss followed by project creation and a relay timeout/error therefore emits ordinary-channel context precisely when project authority is indeterminate.
The checked-in failure regression covers only an empty cache (pool.rs:8565-8614); the expired-negative test at pool.rs:8500-8563 covers successful refresh. A review-only causal mutation seeded expired CachedProjectInfo { value: None } before the malformed-response refresh. cargo test -p buzz-acp failed_project_lookup_through_resolve_cannot_become_ordinary_context -- --nocapture then failed at the intended fail-closed assertion (exit 101), establishing the uncovered branch. Source was restored and the checkout was clean.
Author action: on refresh error, never return stale None as authoritative absence. Propagate ProjectLookupError so resolve() fails closed. If stale Some(project) is intentionally retained for availability, test that policy separately. Add the causal expired-negative → failed-refresh regression through resolve(), and mutation-prove removing the guard fails it.
Verification owner: author for fix/regression; :bot: Jude’s code review agent for exact-new-head mutation and full buzz-acp rerun.
P1 — CLI applies its 10,000-event bound before channel scoping
fetch_projects_for_channel queries community-global kind 30621, calls query_all_bounded(..., 10_000), and only afterward filters buzz-channel client-side (crates/buzz-cli/src/commands/projects.rs:82-96). More than 10,000 unrelated project heads can therefore exhaust or hide valid target-channel discovery. Relay-side #buzz-channel filtering already exists, and ACP uses it; this CLI path omits it.
A review-only production-call-site test captured the exact request from fetch_projects_for_channel and required #buzz-channel. It failed with body [{"kinds":[30621],"limit":500}] at this head. The test was removed and the tree restored clean. Existing project_channel_matching_ignores_unrelated_claims coverage proves only post-fetch matching, not relay query scope.
Author action: add "#buzz-channel": [channel] to the relay filter before query_all_bounded, retaining client filtering as defense in depth. Add a production-call-site regression proving more than 10,000 unrelated events cannot consume the bound, and mutation-prove deleting the filter fails it.
Verification owner: author for fix/regression; :bot: Jude’s code review agent for exact-new-head mutation and full buzz-cli rerun.
Exact-head evidence and residual risk
- Both independent review lanes reproduced their assigned defect against exact head; neither carried prior clearance forward.
- Full
cargo test -p buzz-cli: 377/377 passed. Fullcargo test -p buzz-acp: 812 library + 9 lifecycle tests passed.cargo check -p buzz-cli -p buzz-acpand base-to-headgit diff --checkpassed. These green suites omit the two causal failure shapes above. 73d4e2aa..b4e1d8c1changes onlydesktop/tests/e2e/project-conversation-load-failure.spec.ts:151, selecting the repository before Channels. Exact-head Desktop Smoke E2E (3) is now green, along with Unit Tests, Desktop Core, all other smoke shards, Desktop integrations, relay E2E, Rust Lint, security, and macOS build.- Windows Rust remained in progress at submission. Author action: none unless it fails PR-causally. Verification owner: CI/gate owner for terminal classification.
- No exact-head native Tauri/WebView project-switching artifact or live >10,000-project relay reproduction was produced. Those are confidence gaps, not additional author defects; deterministic production-call mutations establish the blockers.
Gauge round-6 review — head
|
Summary
This is Part 1 of the channel-first Projects stack. Part 2 contains project creation and model foundations.
Testing
cargo fmt --all -- --checkcargo clippy -p buzz-cli -p buzz-acp --all-targets -- -D warningscargo test -p buzz-cli -p buzz-acp— 1,184 tests passed, 1 doc test ignoredPost-Deploy Monitoring & Validation